#pragma once
#include <iostream>
#include <string>
#include <queue>
#include "Mutex.hpp"
#include "Cond.hpp"
#include <pthread.h>
using namespace CondModel;
using namespace MutexModel;


template<class T>
class BlockQueue{
    public:
    BlockQueue(int cap = 5):
        pslp_n(0),cslp_n(0),_cap(cap)
    {
        _cap = cap;
    }
    bool isfull(){return bq.size()>=_cap;}
    bool isempty(){return bq.size()<=0;}
    void inqueue(const T &data){
        Guard lockguard(&mutex);
        while(isfull()){
            pslp_n++;
            std::cout << "生产者，进入休眠了: _psleep_num" << pslp_n << std::endl;
            full_cond.Wait(mutex);
            //pthread_cond_wait(&full_cond,&mutex);
            pslp_n--;
        }
        bq.push(data);
        if(cslp_n > 0)
        {
            empty_cond.Singal();
            //pthread_cond_signal(&empty_cond);
            std::cout << "唤醒消费者" << std::endl;
        }
        //pthread_cond_signal(&empty_cond);
        //pthread_mutex_unlock(&mutex);
    }
    T popqueue(){
        Guard lockguard(&mutex);
        //pthread_mutex_lock(&mutex);
        while(isempty()){
            cslp_n++;
            //pthread_cond_wait(&empty_cond,&mutex);
            std::cout << "消费者，进入休眠了: _csleep_num" << pslp_n << std::endl;

            empty_cond.Wait(mutex);
            cslp_n--;
        }
        T _data = bq.front();
        bq.pop();

        if(pslp_n > 0)
        {
            //slepp(2);
            full_cond.Singal();
            //pthread_cond_signal(&full_cond);
            std::cout << "唤醒生产者" << std::endl;
        }
        //pthread_cond_signal(&full_cond);
        ///pthread_mutex_unlock(&mutex);
        return _data;
    }
    ~BlockQueue(){

    }
    private:
    std::queue<T> bq;
    int _cap;

    Mutex mutex;
    Cond full_cond;
    Cond empty_cond;

    int pslp_n;
    int cslp_n;
    
};